package com.ft.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ft.dao.LostarticleDao;
import com.ft.dao.MoneyDao;
import com.ft.dao.TzmarketDao;
import com.ft.dao.UserDao;
import com.ft.domain.*;
import com.ft.service.ITzmarketService;
import com.ft.utils.ObjectUtils;
import com.ft.websocket.service.ChatEndpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author com/ft
 * @since 2022-08-24
 */
@Service
public class TzmarketServiceImpl extends ServiceImpl<TzmarketDao, Tzmarket> implements ITzmarketService {
    @Autowired
    private TzmarketDao tzmarketDao;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    private UserDao  userDao;
    @Autowired
    private MoneyDao moneyDao;
    /**
     * 创建跳蚤市场订单
     * @param order 跳转市场订单对象
     * @return 受影响的行数
     */
    @Override
    public int createTzmarket(Tzmarket order) throws IllegalAccessException {
        /**
         * 先存redis,在存数据库，最后存数据库成功后进行校验，保证数据库和redis里都有数据并且一致
         *  1.封装订单编号，存入tzmarketIdZset所有订单集合中
         *  oldBuyOrderId: 获取添加Zset前的个数
         *  id ：订单id
         */
        Long oldTzmarketId = redisTemplate.opsForZSet().zCard("tzmarketId");
        String id = String.valueOf(order.getId());
        redisTemplate.opsForZSet().add("tzmarketId",id,1);

        /**
         *  3.封装订单信息，存入Hsah里
         *  格式：订单类型 : 用户id : 订单号
         *  orderKey1：封装hash的key值
         *  stringObjectMap：得到对象属性的map集合
         */
        String orderKey1 = "tzmarket:"+order.getId ();
        Map<String, Object> stringObjectMap = ObjectUtils.objectToMap (order);
        redisTemplate.opsForHash ().putAll (orderKey1, stringObjectMap);
        /**
         * 4.将数据存入数据库
         */
        int buyOrder = tzmarketDao.createTzmarket (order);
        /**
         * 数据校验，保证数据一致性
         * newBuyOrderId：获取添加后的所有订单的Zset个数
         * newlistsize:添加后的用户未付款list集合长度
         * hashOrderStr：获取存入redis的数据
         * hashOrderSize ：订单表所有字段的和
         */
        if (buyOrder == 1 ){
            while (true){
                Long newBuyOrderId = redisTemplate.opsForZSet().zCard("tzmarketId");
                Long  hashOrderSize = redisTemplate.opsForHash().size (orderKey1);
                //结束条件
                if(newBuyOrderId > oldTzmarketId  & hashOrderSize == Tzmarket.total){
                    break;
                }
                //对存入订单id进行校验
                if(newBuyOrderId <= oldTzmarketId){
                    redisTemplate.opsForZSet().add("tzmarketId",id,1);
                    continue;
                }
                //对hash订单表进行校验
                if(hashOrderSize != Tzmarket.total){
                    //移除key
                    redisTemplate.delete (orderKey1);
                    //重新添加
                    Map<String, Object> stringObjectMap1 = ObjectUtils.objectToMap (order);
                    Set mapkey1 = stringObjectMap.keySet ();
                    for(Object key : mapkey1){
                        redisTemplate.opsForHash().put(orderKey1,key,stringObjectMap.get (key));
                    }
                }
            }
            //同步订单创建时间
            redisTemplate.opsForHash().delete(orderKey1,"createTime");
            String time = tzmarketDao.getcreateTime (order.getId ());
            redisTemplate.opsForHash().put(orderKey1,"createTime",time);
            //将id添加到自己创建的跳转订单集合中
            redisTemplate.opsForSet().add(order.getIssueUser()+"issue:tzmarket",id);
            return 1;
        }else {
            //存入数据库失败，删除缓存数据
            redisTemplate.boundZSetOps ("tzmarketId").remove (id);
            redisTemplate.delete (orderKey1);
            return 0;
        }
    }

    /**
     * 查询订单的所有信息
     * @param id 订单id
     * @return
     */
    @Override
    public Tzmarket selectTzmarket(Long id) {
        Tzmarket tzmarket = tzmarketDao.selectTzmarket(id);
        return tzmarket;
    }

    /**
     * 查询用于支付订单的信息
     * @param id 订单id
     * @return
     */
    @Override
    public Tzmarket selectTzmarketToPay(Long id) {
        Tzmarket tzmarket = tzmarketDao.selectTzmarketToPay (id);
        return tzmarket;
    }

    /**
     * 购买用户付款后，修改订单状态
     * @return 返回受影响的结果
     */
    @Override
    public int updataOrder(int state,String id,int belongUserid) throws IOException, IllegalAccessException {
        int i = tzmarketDao.updataOrder (state,id,belongUserid);
        Tzmarket tzmarket = tzmarketDao.selectTzmarket(Long.valueOf(id));
        User user = userDao.selectUserAllById(belongUserid);
        String key ="tzmarket:"+id;
        if(i == 1){
            //将订单类型zet集合中的对应订单id的score值加1
            redisTemplate.opsForZSet().incrementScore ("tzmarketId",id,1);
            //修改订单hash表state状态
            redisTemplate.opsForHash().delete(key,state);
            redisTemplate.opsForHash().put(key,"state",1);
            //更新订单时间
            redisTemplate.opsForHash().delete(key,"updateTime");
            String time = tzmarketDao.getupdateTime(Long.valueOf (id));
            redisTemplate.opsForHash().put(key,"updateTime",time);
            //向自己的购买的订单集合集合中添加id
            String key1 = belongUserid+":buytzmarketorder";
            redisTemplate.opsForSet().add(key1,id);
            //给卖家推送消息
            //设置消息内容
            String msg = "订单标题为:"+tzmarket.getTitle()+"的订单,被用户:"+user.getName() +"购买了";
            int T = ChatEndpoint.orderMessage(String.valueOf(tzmarket.getIssueUser()),user.getName(),msg);
            return 1;
        }else {
            return 0;
        }
    }
    /**
     * 跳蚤市场分页获取订单数据
     * @param page
     * @return
     */
    @Override
    public List getOrder(int type,int page) {
        //同类型的集合数据
        List resulttype = new ArrayList ();
        //返回的数据
        List result = new ArrayList ();
        //获取所有订单数据
        Set tzmarketId = redisTemplate.opsForZSet ().reverseRangeByScore("tzmarketId", 1, 999);
        //遍历set获取同类型的数据
        for(Object le : tzmarketId){
            Map entries = redisTemplate.opsForHash ().entries ("tzmarket:" + le);
            int T = (int) entries.get ("type");
            int state = (int) entries.get("state");
            System.out.println("state:"+state);
            if(T == type + 1 & state == 0){
                //对id进行处理
                Object id = entries.get ("id");
                entries.put ("id",""+id);
                resulttype.add (entries);
            }
        }
        //如果数据小于5的情况
        if(resulttype.size() < 5){
            for(int i = 0;i < resulttype.size(); i++){
                //将map转成对象
                result.add (JSONObject.parseObject(JSONObject.toJSONString(resulttype.get(i)), Tzmarket.class));
            }
            return result;
        }else {
            //每次返回5个数据，total：获取数据结束的位置
            int total = 0;
            //每次获取数据循环开始的位置
            int num = page * 5;
            if(page == 0){
                total = 5;
            }else {
                total = (page+1) * 5;
            }
            for (;num < total & num < resulttype.size(); num++){
                Tzmarket lostarticle = JSONObject.parseObject (JSONObject.toJSONString (resulttype.get (num)), Tzmarket.class);
                result.add (lostarticle);
            }
            return result;
        }
    }

    /**
     * 搜索内容
     * @param content 搜索的数据
     * @return
     */
    @Override
    public List search(String content,int type,int page) {
        //返回结果集合
        List result = new ArrayList ();
        //获取订单数据
        Set buyorderId = redisTemplate.opsForZSet ().reverseRangeByScore("tzmarketId", 1, 999);
        //遍历集合取出数据
        for(Object key : buyorderId){
            Map entries = redisTemplate.opsForHash ().entries ("tzmarket:" + key);
            String ct = (String) entries.get ("content");
            Integer type1 = (Integer) entries.get ("type");
            int state = (int) entries.get("state");
            if(type1 == type+1 & ct.contains (content) & state == 0 ){
                //对id进行处理
                Object id = entries.get ("id");
                entries.put ("id",""+id);
                result.add(entries);
            }
        }
        //数据小于5的情况
        if(result.size() < 5){
            return result;
        }else {
            List ids = new ArrayList();
            //每次返回5个数据，total：获取数据结束的位置
            int total = 0;
            //每次获取数据循环开始的位置
            int num = page * 5;
            if(page == 0){
                total = 5;
            }else {
                total = (page+1) * 5;
            }
            for(;num < total & num < result.size (); num++){
                ids.add (result.get(num));
            }
            return ids;
        }
    }

    /**
     * 发布用户取消订单
     * @param orderid
     * @return
     */
    @Override
    public int updateOrderRefund(String orderid) {
        int state = tzmarketDao.getState(Long.valueOf(orderid));
        if(state == -1){
            return 2;
        }
        //更新数据库
        int i = tzmarketDao.updateOrderRefund(orderid);
        if(i == 1){
            //处理缓存
            String key = "tzmarket:" + orderid;
            //修改订单hash表state状态
            redisTemplate.opsForHash().put(key, "state", -1);
            String time = tzmarketDao.getupdateTime(Long.valueOf(orderid));
            redisTemplate.opsForHash().put(key, "updateTime", time);
            return 1;
        }
        return 0;
    }

    /**
     * 购买用户退款,取消购买订单
     * @param orderid
     * @return
     */
    @Override
    public int buyUserRefund(String orderid) throws IOException, IllegalAccessException {
        Tzmarket tzmarket = tzmarketDao.selectTzmarket(Long.valueOf(orderid));
        if(tzmarket.getState() == 4 | tzmarket.getState() == 3){
            return 2;
        }
        String username = tzmarket.getIssueUserName();
        //获取购买用户名称
        User belongname = userDao.selectUserAllById(tzmarket.getBelongUser());
        int i = tzmarketDao.buyUserRefund(orderid);
        if(i == 1){
            String key = "tzmarket:" + orderid;
            //修改订单hash表state状态
            redisTemplate.opsForHash().put(key, "state", 0);
            //更新订单时间
            String time = tzmarketDao.getupdateTime(Long.valueOf(orderid));
            redisTemplate.opsForHash().put(key, "updateTime", time);
            //将购买订单移除集合
            String key1 = tzmarket.getBelongUser() +":buytzmarketorder";
            redisTemplate.opsForSet().remove(key1, orderid);
            //设置给卖家消息内容
            String msg = "用户:"+belongname.getName() +"取消了购买名为:"+ tzmarket.getTitle() +"订单";
            int T = ChatEndpoint.orderMessage(String.valueOf(tzmarket.getIssueUser()),username,msg);
            //设置给买家消息
            //给购买用户推送消息
            String msg1 = "您:" +"取消了购买名为:"+ tzmarket.getTitle() +"订单，金额："+tzmarket.getPrice()+"元以原路返回";
            int T1 = ChatEndpoint.orderMessage(String.valueOf(tzmarket.getBelongUser()),username,msg1);
            System.out.println("买家："+belongname.getName()+"买家:"+username);
            if(T == 1 & T1 == 1){
                return 1;
            }
            return 0;
        }
        return 0;
    }


    /**
     * 购买用户确认完成订单
     * @param orderid
     * @return
     */
    @Override
    public int issueOverOrder(String orderid, int userid) throws IOException, IllegalAccessException {
        //获取订单信息
        Tzmarket order = tzmarketDao.selectTzmarket(Long.valueOf(orderid));
        if(order.getState() != 1 ){
            return  2;
        }
        //获取付款用户信息
        User user = userDao.selectUserAllById(order.getBelongUser());
        if(user == null){
            return 2;
        }
        int i = tzmarketDao.issueaccomplishOrder(orderid);
        // 修改对应用户的金额
        //手续费
        BigDecimal rate = new BigDecimal(""+0.06);
        //订单价格
        BigDecimal money = new BigDecimal(""+order.getPrice());
        //卖家的收入
        BigDecimal income = money.subtract(money.multiply(rate));
        //结果保留2位小数，4舍，5入
        double requestMoney = income.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        //获取发布用户的money
        double userMoney = userDao.getUserMoney(order.getIssueUser());
        //对精度处理
        BigDecimal p1 = new BigDecimal(Double.toString(requestMoney));
        BigDecimal p2 = new BigDecimal(Double.toString(userMoney));
        //总价
        BigDecimal tataleMoney = p1.add(p2);
        //更新发布用户金额
        int i1 = userDao.updateUserMoney(tataleMoney, order.getIssueUser());
        //创建交易明细表
        MoneyInfo moneyInfo = new MoneyInfo();
        moneyInfo.setMoney(requestMoney);
        moneyInfo.setIssueuser(order.getIssueUser());
        moneyInfo.setContinueuser(order.getBelongUser());
        moneyInfo.setGetmoenyorderid(order.getId());
        int i2 = moneyDao.addMoneyInfo(moneyInfo);
        if(i == 1 & i1 == 1 & i2 == 1){
            //修改缓存中的订单状态
            String key = "tzmarket:" + orderid;
            //修改订单hash表state状态
            redisTemplate.opsForHash().put(key, "state", 3);
            String time = tzmarketDao.getupdateTime(Long.valueOf(orderid));
            redisTemplate.opsForHash().put(key, "updateTime", time);
            //设置消息内容
            String msg = "用户:"+user.getName() +"确认完成了订单标题为:"+order.getTitle()+"的订单,金额为："+ requestMoney +"元已到账！";
            int T = ChatEndpoint.orderMessage(String.valueOf(order.getIssueUser()),user.getName(),msg);
            if(T == 1){
                return 1;
            }
            return 0;
        }
        return 0;
    }

    /**
     * 获取用户已发布订单
     * @return
     */
    @Override
    public List getUserissueTzmarket(int userid){
        String key = userid + "issue:tzmarket";
        List result = new ArrayList();
        Set orderOkId = redisTemplate.boundSetOps(key).members();
        List ids = new ArrayList<>(orderOkId);
        //获取订单数据返回
        for (int i = 0; i < ids.size(); i++) {
            Map entries = redisTemplate.opsForHash().entries("tzmarket:" + ids.get(i));
            //对订单号处理成字符串，防止前端精度丢失
            Object id = entries.get("id");
            entries.put("id", "" + id);
            result.add(entries);
        }
        return result;
    }

    /**
     * 获取用户购买订单
     * @param userid
     * @return
     */
    @Override
    public List getUserBuyorders(int userid){
        String key = userid+":buytzmarketorder";
        List result = new ArrayList();
        Set orderOkId = redisTemplate.boundSetOps(key).members();
        List ids = new ArrayList<>(orderOkId);
        //获取订单数据返回
        for (int i = 0; i < ids.size(); i++) {
            Map entries = redisTemplate.opsForHash().entries("tzmarket:" + ids.get(i));
            //对订单号处理成字符串，防止前端精度丢失
            Object id = entries.get("id");
            entries.put("id", "" + id);
            result.add(entries);
        }
        return result;
    }

    /**
     * 获取订单状态
     * @param orderid
     * @return
     */
    @Override
    public int getState(String orderid){
        int state = tzmarketDao.getState(Long.valueOf(orderid));
        return state;
    }
}
